import re

from django.conf import settings
from django.core.cache import cache
from itsdangerous import URLSafeSerializer
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings

from .models import User, OAuthQQUser, Address
from .tasks import send_email

class UserSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(max_length=6,write_only=True)
    password2 = serializers.CharField(max_length=20,min_length=8,write_only=True)
    allow = serializers.CharField(write_only=True)
    token = serializers.CharField(read_only=True)
    class Meta:
        model = User
        fields = ("id","username","mobile","email","sms_code","password2","allow","password","token")
        extra_kwargs = {
            "password": {
                'max_length':20,
                'min_length':8,
                'write_only':True,
                'error_messages':{
                    "max_length":"密码过长",
                    "min_length":"密码过短"
                }
            },
            "username": {
                "max_length":20,
                "min_length":5,
                'error_messages':{
                    "max_length":'名字过长',
                    "min_length":'名字过短'
                }
            }
        }

    # 手机验证
    def validate_mobile(self,mobile):
        if not re.match(r"^1[3-9]\d{9}$",mobile):
            raise serializers.ValidationError("手机格式不正确")
        return mobile

    # 验证校验
    def validate_allow(self,allow):
        if allow != 'true':
            raise serializers.ValidationError("未统一协议")
        return allow

    # 验证密码和手机验证码
    def validate(self, attrs):
        if attrs["password"] != attrs["password2"]:
            raise serializers.ValidationError("密码不一致")
        real_sms_code = cache.get("sms_code_%s" % attrs['mobile'])
        if not real_sms_code:
            raise serializers.ValidationError("验证码失效")
        if real_sms_code != int(attrs["sms_code"]):
            raise serializers.ValidationError("验证码错误1")
        return attrs

    # 保存数据
    def create(self, validated_data):

        del validated_data['password2']
        del validated_data['sms_code']
        del validated_data['allow']
        user = super().create(validated_data)

        # 调用django的认证系统加密密码
        user.set_password(validated_data['password'])
        user.save()
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token
        user.token = token
        return user


class QQAuthUserSerializer(serializers.ModelSerializer):
    # 写个序列化器需要哪些问题。入哪些参数，出参有哪些，模型类有哪些字段 字段
    sms_code = serializers.CharField(max_length=4, write_only=True)
    access_token = serializers.CharField(write_only=True)
    token = serializers.CharField(read_only=True)
    class Meta:
        model = User
        fields = ("sms_code","mobile","password","access_token","username","token")
        read_only_fields = ('username',)
        extra_args = {
            'password': {
                'max_length': 20,
                'min_length': 8,
                'write_only': True,
                'error_messages': {
                    'max_length': '密码过长'
                }
            },
            'mobile': {
                'max_length': 11,
                'min_length': 11,
                'error_messages': {
                    'max_length': '名字过长',
                    'min_length': '名字过短'

                }
            },
        }
    def validate(self, attrs):
        # 检查openid
        secret = URLSafeSerializer(settings.SECRET_KEY, "qq")
        try:
            data = secret.loads(attrs["access_token"])
        except:
            raise serializers.ValidationError("错误的access_token")
        openid = data.get("openid")
        attrs['openid'] = openid
        # 检查sms_code
        real_sms_code = cache.get("sms_code_%s" % attrs['mobile'])
        if not real_sms_code:
            raise serializers.ValidationError("验证码失效")
        if real_sms_code != int(attrs["sms_code"]):
            raise serializers.ValidationError("验证码错误")
        try:
            user = User.objects.get(mobile =attrs['mobile'])
        except:
            return attrs
        else:
            if user.check_password(attrs["password"]):
                attrs["user"] = user
                return attrs
            else:
                raise serializers.ValidationError("密码错误")

    def create(self, validated_data):
        user = validated_data.get("user",None)
        if user is None:
            user = User.objects.create_user(username=validated_data["mobile"],mobile=validated_data["mobile"],
                              password = validated_data["password"])
        OAuthQQUser.objects.create(user=user,openid=validated_data["openid"])

        # 生成jwt—token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        # 对user对象添加token属性字段
        user.token = token
        # 合并购物车时使用
        self.context["view"].user = user
        return user


class UserDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'mobile', 'username', 'email', 'email_active')


class EmailSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'email')
        extra_kwargs = {
            'email':{
                'required': True
            }
        }

    def update(self, instance, validated_data):
        email = validated_data['email']
        secret_email = URLSafeSerializer(settings.SECRET_KEY, "email")
        token = secret_email.dumps({"username":instance.username})
        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=' + token
        send_email.delay(email,verify_url)
        instance.email = email
        instance.save()
        return instance


class AddressSerializer(serializers.ModelSerializer):
    province = serializers.StringRelatedField(label='省', read_only=True)
    city = serializers.StringRelatedField(label='市', read_only=True)
    district = serializers.StringRelatedField(label='区', read_only=True)
    province_id = serializers.IntegerField(write_only=True)
    city_id = serializers.IntegerField(write_only=True)
    district_id = serializers.IntegerField(write_only=True)

    class Meta:
        model = Address
        exclude = ('user',)

    def create(self, validated_data):

        # 获取用户对象
        user = self.context['request'].user

        validated_data['user'] = user
        # 调用父类方法，进行保存
        address = super().create(validated_data)

        return address